package dreadnought;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/*
 * This is the main Game class and the main panel
 * Most classes in dreadnought will have a reference to an
 * instance of this class so any game wide constants should
 * be put in here as public variables.
 */
public class Game extends JPanel
{
    public PlayerGrid playerGrid;
    
    public EnemyGrid enemyGrid;

    //a reference to the selected ship
    //the player can only select one of his/her own ship
    public Ship selectedShip; 

    //the size of each square cell of the grid
    public final int CELL = 40;

    //the padding around the grid
    public final int PAD = 20;
    
    //the current state of the game
    private GameState state;

    //the previous state of the game, immediately before the current state
    private GameState prevState;

    //this array is used to convert to and from alphanumeric
    //representation of coordinates eg: A4, B6, J1 etc...
    public final char[] chars = {'A','B','C','D','E','F','G','H','I','J'};

    public Random rand;
    
    private JButton deploymentCompleteButton;

    public JLabel infoLabel;
    private JTextArea log;
    private JScrollPane scrollPane;

    //colors
    public final Color COLORS_WATER = Color.decode("#306EFF");
    public final Color COLORS_SHIP = Color.decode("#555555");
    public final Color COLORS_HIT = Color.decode("#E42217");
    public final Color COLORS_MISS = Color.decode("#2554C7");
    public final Color COLORS_HIGHLIGHT = Color.decode("#F9A7B0");
    public final Color COLORS_BACKGROUND = Color.decode("#EEEEEE");

    //flags
    public final boolean SHOW_HEURISTIC_COLORS = true;
    public final boolean AUTOPLAY = false;
    private final int AUTOPLAY_SPEED = 100; //ms

    //for counting how many turns each player has
    private int player1Turns;
    private int player2Turns;

    private javax.swing.Timer timer;
    
    public Game()
    {
        this.player1Turns = 0;
        this.player2Turns = 0;
        
        //set inital game state
        this.state = GameState.DEPLOYMENT;

        //instatiate rand
        this.rand = new Random();
        
        //set the size of the main game panel
        this.setPreferredSize(new Dimension(1000,600));
        this.setBackground(this.COLORS_BACKGROUND);

        //instantiate the player grid
        this.playerGrid = new PlayerGrid(this);
        this.add(this.playerGrid);

        //instantiate the enemy grid
        this.enemyGrid = new EnemyGrid(this);
        this.add(this.enemyGrid);
        
        this.deploymentCompleteButton = new JButton("Deployment Complete");
        this.deploymentCompleteButton.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e){
            if (!playerGrid.shipsOverlap())
            {
                startTurns();
            }
            else
            {
                JOptionPane.showMessageDialog(null,
                        "Some ships overlap, please correct this problem.");
            }
        }});
        this.add(this.deploymentCompleteButton);

        this.infoLabel = new JLabel("" +
                "Deploy your ships. \n" +
                "Click a ship to select it. \n" +
                "Move selected ship with arrow keys. \n" +
                "Toggle ship orientation with space bar.");
        this.add(this.infoLabel);

        //set up game log text area
        this.log = new JTextArea(6,50);
        this.scrollPane = new JScrollPane(this.log);
        this.add(this.scrollPane);
        this.log.append("Deployment\n");

        this.timer = new javax.swing.Timer(AUTOPLAY_SPEED, new TimerListener());
        if (AUTOPLAY)
            timer.start();
    }

    public void startTurns()
    {
        this.selectedShip = null;
        this.state = GameState.PLAYER_TURN;
        this.deploymentCompleteButton.setVisible(false);
        this.infoLabel.setText("Click an enemy cell to fire upon.");
        this.playerTurn();
    }

    //this method is at the beginning of each of the players turns
    public void playerTurn()
    {
        this.player1Turns += 1;
    }

    public void playerAutoPlay()
    {
        //GridCoordinate coord = this.enemyGrid.stochasticallyChooseTarget();
        GridCoordinate coord = this.enemyGrid.randomUnhitCoordinate();
        this.enemyGrid.fire(coord);
    }
    

    //this method is at the beginning of each of the players turns
    public void enemyTurn()
    {
        this.player2Turns += 1;
        
        GridCoordinate coord = this.playerGrid.stochasticallyChooseTarget();
        this.playerGrid.fire(coord);
    }

    //this method is at the beginning of each of the players turns
    public void gameOver()
    {
        String msg = "Game Over\n"
                + "player1Turns: " + this.player1Turns + "\n"
                + "player2Turns: " + this.player2Turns + "\n";
        this.writeToLog(msg);
        this.alert(msg);
    }

    //this method will be called whenever a turn ends
    public void turnEvent()
    {
        /*
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {}
         * */
        
        if (state == GameState.PLAYER_TURN)
            playerTurn();
        else if (state == GameState.ENEMY_TURN)
            enemyTurn();
        else if (state == GameState.GAMEOVER)
            gameOver();
        else
            this.infoLabel.setText("unkown state");
    }
    
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
    }

    //writes some text the the game log
    public void writeToLog(String msg)
    {
        //append the message to the end of the log
        this.log.append(msg);
        //set the cursor of the log text area to the bottom so that the
        //latest few lines will be visible and the older lines hidden
        this.log.setCaretPosition(this.log.getText().length()-1);
    }

    //sets the game state and records the old state
    public void setState(GameState s)
    {
        this.prevState = this.state;
        this.state = s;
    }

    //returns the current game state
    public GameState getState()
    {
        return this.state;
    }

    /**
     * displays a message dialog box with the given string
     * @param msg the message to display
     */
    public void alert(String msg)
    {
        if (!this.AUTOPLAY)
            JOptionPane.showMessageDialog(null, msg);
    }

    private class TimerListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            if (state == GameState.PLAYER_TURN)
                playerAutoPlay();
        }
    }
}